package cuongnh.project.japanesediary.vocabulary.ui.editor.vocabulary.page.related.section;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ObservableSetContentProvider;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

import cuongnh.project.japanesediary.vocabulary.application.Activator;
import cuongnh.project.japanesediary.vocabulary.common.CommonServices;
import cuongnh.project.japanesediary.vocabulary.common.CommonUtils;
import cuongnh.project.japanesediary.vocabulary.model.Vocabulary;
import cuongnh.project.japanesediary.vocabulary.ui.dialog.AddRelatedVocabularyDialog;

public class HomophoneVocabulariesSection extends SectionPart {
	private DataBindingContext m_bindingContext;
	private Vocabulary vocabulary;
	private CommonServices commonServices;
	private TableViewer tblHomophoneVocabularies;

	/**
	 * Create the SectionPart.
	 * 
	 * @param parent
	 * @param toolkit
	 * @param style
	 */
	public HomophoneVocabulariesSection(Composite parent, FormToolkit toolkit,
			int style, Vocabulary vocabulary, CommonServices commonServices) {
		super(parent, toolkit, style);
		this.vocabulary = vocabulary;
		this.commonServices = commonServices;
		createClient(getSection(), toolkit);
	}

	private void initData() {
		vocabulary = commonServices.getVocabularyDao()
				.getVocabularyWithHomophones(vocabulary.getVocabularyId());
	}

	/**
	 * Fill the section.
	 */
	private void createClient(Section section, FormToolkit toolkit) {
		section.setText("Homophone Vocabularies");
		Composite container = toolkit.createComposite(section);
		section.setClient(container);
		toolkit.paintBordersFor(container);
		createToolBar(section);

		Composite compRelatedVocabulary = new Composite(section, SWT.NONE);
		toolkit.adapt(compRelatedVocabulary);
		toolkit.paintBordersFor(compRelatedVocabulary);
		section.setClient(compRelatedVocabulary);

		tblHomophoneVocabularies = new TableViewer(compRelatedVocabulary,
				SWT.BORDER | SWT.FULL_SELECTION);
		Table table = tblHomophoneVocabularies.getTable();
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		tblHomophoneVocabularies.getTable().setLinesVisible(true);
		tblHomophoneVocabularies.getTable().setHeaderVisible(true);

		TableViewerColumn tbclvVocabulary = new TableViewerColumn(
				tblHomophoneVocabularies, SWT.NONE);
		TableColumn tblclmnVocabulary = tbclvVocabulary.getColumn();
		tblclmnVocabulary.setWidth(100);
		tblclmnVocabulary.setText("Vocabulary");

		TableViewerColumn tbclvFurigana = new TableViewerColumn(
				tblHomophoneVocabularies, SWT.NONE);
		TableColumn tblclmnFurigana = tbclvFurigana.getColumn();
		tblclmnFurigana.setWidth(100);
		tblclmnFurigana.setText("Furigana");

		TableViewerColumn tbclvHanviet = new TableViewerColumn(
				tblHomophoneVocabularies, SWT.NONE);
		TableColumn tblclmnHanviet = tbclvHanviet.getColumn();
		tblclmnHanviet.setWidth(100);
		tblclmnHanviet.setText("HAN-VIET");

		TableViewerColumn tbclvVnMeaning = new TableViewerColumn(
				tblHomophoneVocabularies, SWT.NONE);
		TableColumn tblclmnVietnameseMeaning = tbclvVnMeaning.getColumn();
		tblclmnVietnameseMeaning.setWidth(100);
		tblclmnVietnameseMeaning.setText("Vietnamese meaning");

		// Specify column's width by a percentage
		TableColumnLayout tblColumnLayout = new TableColumnLayout();
		tblColumnLayout.setColumnData(tblclmnVocabulary, new ColumnWeightData(
				25, true));
		tblColumnLayout.setColumnData(tblclmnFurigana, new ColumnWeightData(20,
				true));
		tblColumnLayout.setColumnData(tblclmnHanviet, new ColumnWeightData(15,
				true));
		tblColumnLayout.setColumnData(tblclmnVietnameseMeaning,
				new ColumnWeightData(35, true));
		compRelatedVocabulary.setLayout(tblColumnLayout);

		CommonUtils
				.vocabulariesHookDoubleClickCommand(tblHomophoneVocabularies);
		initData();
		m_bindingContext = initDataBindings();
	}

	private void createToolBar(final Section section) {
		ToolBar toolbar = new ToolBar(section, SWT.FLAT);
		section.setTextClient(toolbar);

		ToolItem addItem = new ToolItem(toolbar, SWT.PUSH);
		addItem.setImage(Activator.getImageDescriptor("/icons/add.gif")
				.createImage());
		addItem.setToolTipText("Add a related Vocabulary to this Vocabulary");

		addItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				AddRelatedVocabularyDialog relatedVocabularyDialog = new AddRelatedVocabularyDialog(
						section.getShell(), commonServices);
				if (relatedVocabularyDialog.open() == Window.OK) {
					Set<Vocabulary> selectedVocabularies = relatedVocabularyDialog
							.getSelectedVocabularies();
					if (!selectedVocabularies.isEmpty()) {
						// update selected vocabulary as a related vocabulary
						// for current vocabulary
						vocabulary.getVocabularyHomophones().addAll(
								selectedVocabularies);
						commonServices.getVocabularyDao().merge(vocabulary);

						for (Vocabulary selectedVocabulary : selectedVocabularies) {
							// update current vocabulary as a related vocabulary
							// of
							// selected vocabulary
							selectedVocabulary = commonServices
									.getVocabularyDao()
									.getVocabularyWithHomophones(
											selectedVocabulary
													.getVocabularyId());
							selectedVocabulary.getVocabularyHomophones().add(
									vocabulary);
							commonServices.getVocabularyDao().merge(
									selectedVocabulary);
						}

						// add selected vocabulary to the Related vocabularies
						// table to display
						vocabulary.getVocabularyHomophones().addAll(
								selectedVocabularies);

						m_bindingContext.updateModels();
						tblHomophoneVocabularies.refresh();
						tblHomophoneVocabularies.setSelection(new StructuredSelection(selectedVocabularies.toArray()));
					}
				}
			}
		});

		ToolItem removeItem = new ToolItem(toolbar, SWT.PUSH);
		removeItem.setImage(Activator.getImageDescriptor("/icons/delete.gif")
				.createImage());
		removeItem
				.setToolTipText("Remove selected Category that this vocabulary belong to");

		removeItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection selection = (IStructuredSelection) tblHomophoneVocabularies
						.getSelection();
				Set<Vocabulary> selectedVocabularies = new HashSet<Vocabulary>();
				for (Iterator<Vocabulary> iter = selection.iterator(); iter
						.hasNext();) {
					selectedVocabularies.add(iter.next());
				}

				if (!selectedVocabularies.isEmpty()) {
					boolean confirm = MessageDialog.openConfirm(
							section.getShell(), "Deleting confirmation!",
							"Are you sure you want to delete this Vocabulary?");
					if (confirm) {
						// remove selected vocabulary as a related vocabulary
						// for
						// current vocabulary
						vocabulary.getVocabularyHomophones().removeAll(
								selectedVocabularies);
						commonServices.getVocabularyDao().merge(vocabulary);

						for (Vocabulary selectedVocabulary : selectedVocabularies) {
							// remove current vocabulary as a related vocabulary
							// of
							// selected vocabulary
							selectedVocabulary = commonServices
									.getVocabularyDao()
									.getVocabularyWithHomophones(
											selectedVocabulary
													.getVocabularyId());
							selectedVocabulary.getVocabularyHomophones().remove(
									vocabulary);
							commonServices.getVocabularyDao().merge(
									selectedVocabulary);
						}

						// add selected vocabulary to the Related vocabularies
						// table to display
						vocabulary.getVocabularyHomophones().removeAll(
								selectedVocabularies);
					}

					m_bindingContext.updateModels();
					tblHomophoneVocabularies.refresh();
				}

			}
		});
	}

	protected DataBindingContext initDataBindings() {
		DataBindingContext bindingContext = new DataBindingContext();
		//
		ObservableSetContentProvider setContentProvider = new ObservableSetContentProvider();
		IObservableMap[] observeMaps = BeansObservables
				.observeMaps(setContentProvider.getKnownElements(),
						Vocabulary.class, new String[] { "vocabulary",
								"furigana", "hanviet", "vnMeaning" });
		tblHomophoneVocabularies
				.setLabelProvider(new ObservableMapLabelProvider(observeMaps));
		tblHomophoneVocabularies.setContentProvider(setContentProvider);
		IObservableSet homophoneVocabulariesSet = BeanProperties.set(
				"vocabularyHomophones").observe(vocabulary);
		tblHomophoneVocabularies.setInput(homophoneVocabulariesSet);
		//
		return bindingContext;
	}

	@Override
	public void commit(boolean onSave) {
		super.commit(onSave);
		commonServices.getVocabularyDao().merge(vocabulary);
		tblHomophoneVocabularies.refresh();
	}

}
